﻿// Decompiled with JetBrains decompiler
// Type: Sirenix.OdinInspector.Editor.Drawers.CHCHEnumToggleButtonsAttributeDrawer`1
// Assembly: Sirenix.OdinInspector.Editor, Version=3.0.3.0, Culture=neutral, PublicKeyToken=null
// MVID: F165029E-8DA6-44A5-A730-6E9A6AAFCB26
// Assembly location: D:\MirageOfTheFall\Assets\Plugins\Sirenix\Assemblies\Sirenix.OdinInspector.Editor.dll

using Sirenix.Utilities;
using Sirenix.Utilities.Editor;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;

namespace Sirenix.OdinInspector.Editor.Drawers
{
  /// <summary>
  /// Draws an enum in a horizontal button group instead of a dropdown.
  /// </summary>
  public class CHEnumToggleButtonsAttributeDrawer<T> : 
    OdinAttributeDrawer<CHEnumToggleButtonsAttribute, T>
  {
    private static bool DoManualColoring = UnityVersion.IsVersionOrGreater(2019, 3);
    private static Color ActiveColor = EditorGUIUtility.isProSkin ? Color.white : new Color(0.802f, 0.802f, 0.802f, 1f);
    private static Color InactiveColor = EditorGUIUtility.isProSkin ? new Color(0.75f, 0.75f, 0.75f, 1f) : Color.white;
    private GUIContent[] Names;
    private ulong[] Values;
    private float[] NameSizes;
    private bool IsFlagsEnum;
    private List<int> ColumnCounts;
    private float PreviousControlRectWidth;
    private Color?[] SelectionColors;

    /// <summary>
    /// Returns <c>true</c> if the drawer can draw the type.
    /// </summary>
    public override bool CanDrawTypeFilter(System.Type type) => type.IsEnum;

    protected override void Initialize()
    {
      System.Type typeOfValue = this.ValueEntry.TypeOfValue;

      #region 正确显示LabelText的名字

      var names111 = new List<string>();
      var fields   = typeOfValue.GetFields().Skip(1).ToArray();
      foreach (var field in fields) {
        var atb = field.GetCustomAttribute<LabelTextAttribute>();
        if (atb != null) {
          names111.Add(((LabelTextAttribute) atb).Text);
          continue;
        }

        var atb2 = field.GetCustomAttribute<DescriptionAttribute>();
        if (atb2 != null) {
          names111.Add(atb2.Description);
          continue;
        }

        names111.Add(field.Name);
      }

      #endregion

      string[] names = names111.ToArray();
      // string[] names = Enum.GetNames(typeOfValue);
      // var ot = Enum.GetNames(typeOfValue);
      this.Names = ((IEnumerable<string>) names).Select<string, GUIContent>((Func<string, GUIContent>) (x => new GUIContent(x.SplitPascalCase()))).ToArray<GUIContent>();
      this.Values = new ulong[this.Names.Length];
      this.IsFlagsEnum = TypeExtensions.IsDefined<FlagsAttribute>(typeOfValue);
      this.NameSizes = ((IEnumerable<GUIContent>) this.Names).Select<GUIContent, float>((Func<GUIContent, float>) (x => SirenixGUIStyles.MiniButtonMid.CalcSize(x).x)).ToArray<float>();
      this.ColumnCounts = new List<int>()
      {
        this.NameSizes.Length
      };
      GUIHelper.RequestRepaint();
      for (int index = 0; index < this.Values.Length; ++index)
        // this.Values[index] = TypeExtensions.GetEnumBitmask(Enum.Parse(typeOfValue, names[index]), typeOfValue);
        this.Values[index] = TypeExtensions.GetEnumBitmask(Enum.Parse(typeOfValue, Enum.GetNames(typeOfValue)[index]), typeOfValue);
      if (!CHEnumToggleButtonsAttributeDrawer<T>.DoManualColoring)
        return;
      this.SelectionColors = new Color?[this.Names.Length];
    }

    /// <summary>Draws the property.</summary>
    protected override void DrawPropertyLayout(GUIContent label)
    {
      IPropertyValueEntry<T> valueEntry = this.ValueEntry;
      System.Type type = valueEntry.WeakValues[0].GetType();
      for (int index = 1; index < valueEntry.WeakValues.Count; ++index)
      {
        if (type != valueEntry.WeakValues[index].GetType())
        {
          SirenixEditorGUI.ErrorMessageBox("ToggleEnum does not support multiple different enum types.");
          return;
        }
      }
      ulong num1 = TypeExtensions.GetEnumBitmask((object) valueEntry.SmartValue, typeof (T));
      Rect rect = new Rect();
      int index1 = 0;
      for (int index2 = 0; index2 < this.ColumnCounts.Count; ++index2)
      {
        Rect valueRect;
        SirenixEditorGUI.GetFeatureRichControlRect(index2 == 0 ? label : GUIContent.none, out int _, out bool _, out valueRect);
        if (index2 == 0)
          rect = valueRect;
        else
          valueRect.xMin = rect.xMin;
        float xMax = valueRect.xMax;
        valueRect.width /= (float) this.ColumnCounts[index2];
        valueRect.width = (float) (int) valueRect.width;
        int num2 = index1;
        for (int index3 = index1 + this.ColumnCounts[index2]; index1 < index3; ++index1)
        {
          bool flag;
          if (this.IsFlagsEnum)
          {
            ulong enumBitmask = TypeExtensions.GetEnumBitmask((object) this.Values[index1], typeof (T));
            flag = num1 != 0UL ? enumBitmask != 0UL && ((long) enumBitmask & (long) num1) == (long) enumBitmask : enumBitmask == 0UL;
          }
          else
            flag = (long) this.Values[index1] == (long) num1;
          Color? nullable = new Color?();
          if (CHEnumToggleButtonsAttributeDrawer<T>.DoManualColoring)
          {
            Color color = flag ? CHEnumToggleButtonsAttributeDrawer<T>.ActiveColor : CHEnumToggleButtonsAttributeDrawer<T>.InactiveColor;
            nullable = this.SelectionColors[index1];
            if (!nullable.HasValue)
              nullable = new Color?(color);
            else if (nullable.Value != color && Event.current.type == UnityEngine.EventType.Layout)
            {
              float maxDelta = EditorTimeHelper.Time.DeltaTime * 4f;
              nullable = new Color?(new Color(Mathf.MoveTowards(nullable.Value.r, color.r, maxDelta), Mathf.MoveTowards(nullable.Value.g, color.g, maxDelta), Mathf.MoveTowards(nullable.Value.b, color.b, maxDelta), Mathf.MoveTowards(nullable.Value.a, color.a, maxDelta)));
              GUIHelper.RequestRepaint();
            }
            this.SelectionColors[index1] = nullable;
          }
          Rect position = valueRect;
          GUIStyle style;
          if (index1 == num2 && index1 == index3 - 1)
          {
            style = flag ? SirenixGUIStyles.MiniButtonSelected : SirenixGUIStyles.MiniButton;
            --position.x;
            position.xMax = xMax + 1f;
          }
          else if (index1 == num2)
            style = flag ? SirenixGUIStyles.MiniButtonLeftSelected : SirenixGUIStyles.MiniButtonLeft;
          else if (index1 == index3 - 1)
          {
            style = flag ? SirenixGUIStyles.MiniButtonRightSelected : SirenixGUIStyles.MiniButtonRight;
            position.xMax = xMax;
          }
          else
            style = flag ? SirenixGUIStyles.MiniButtonMidSelected : SirenixGUIStyles.MiniButtonMid;
          if (CHEnumToggleButtonsAttributeDrawer<T>.DoManualColoring)
            GUIHelper.PushColor(nullable.Value * GUI.color);
          if (GUI.Button(position, this.Names[index1], style))
          {
            GUIHelper.RemoveFocusControl();
            if (!this.IsFlagsEnum || Event.current.button == 1 || Event.current.modifiers == EventModifiers.Control)
            {
              valueEntry.WeakSmartValue = Enum.ToObject(typeof (T), this.Values[index1]);
            }
            else
            {
              if (this.Values[index1] == 0UL)
                num1 = 0UL;
              else if (flag)
                num1 &= ~this.Values[index1];
              else
                num1 |= this.Values[index1];
              valueEntry.WeakSmartValue = Enum.ToObject(typeof (T), num1);
            }
            GUIHelper.RequestRepaint();
          }
          if (CHEnumToggleButtonsAttributeDrawer<T>.DoManualColoring)
            GUIHelper.PopColor();
          valueRect.x += valueRect.width;
        }
      }
      if (Event.current.type != UnityEngine.EventType.Repaint || (double) this.PreviousControlRectWidth == (double) rect.width)
        return;
      this.PreviousControlRectWidth = rect.width;
      float b = 0.0f;
      int index4 = 0;
      this.ColumnCounts.Clear();
      this.ColumnCounts.Add(0);
      for (int index2 = 0; index2 < this.NameSizes.Length; ++index2)
      {
        float a = this.NameSizes[index2] + 3f;
        int num2 = ++this.ColumnCounts[index4];
        float num3 = rect.width / (float) num2;
        b = Mathf.Max(a, b);
        if ((double) b > (double) num3 && num2 > 1)
        {
          this.ColumnCounts[index4]--;
          this.ColumnCounts.Add(1);
          ++index4;
          b = a;
        }
      }
    }
  }
}
